'''
# 1.skip()函数
# skip()函数的功能是将笔画移动指定的距离,它包含了抬起笔画,移动画笔和落下画笔三个固定的步骤,
# 绘制壳都市,无论是绘制线段还是圆点,都会设计到画笔的移动,为了避免多个位置出现重复的代码,所以设计了skip()函数,'''

import turtle   # 导入turtle绘图库
from datetime import datetime  # 从datetime模块导入datetime类，用于获取当前时间

def skip(step):
    '''将画笔移动到指定位置'''
    turtle.penup() # 抬起画笔，移动时不画线
    turtle.forward(step) # 向前移动step指定的距离
    turtle.pendown() # 落下画笔，准备画线

'''
# 2.setup_clock函数
# 功能是绘制中标刻度,该函数在绘制钟表刻度时,以钟表中心为起点,从中心位置开始移动画笔到指定位置落笔,绘制完线段
# 或原点之后再次回到中心店,改变画笔的角度,移动画笔到指定的位置落笔绘制下一个刻度'''

def setup_clock(radius):
    '''建立钟表的外框'''
    turtle.reset() # 重置turtle状态（位置、方向等）
    turtle.pensize(7) # 设置画笔粗细为7
    for i in range(60): #循环60次（对应60个刻度
        skip(radius) # 从中心点（0,0）移动到圆周上（半径radius处）
        if i%5 == 0: # 每5个刻度（即小时刻度）
            turtle.forward(20) # 画一条长20像素的线（小时刻度线）
            skip(-radius-20) # 往回移动（半径+20）像素，回到中心点
        else:        # 不是小时刻度
            turtle.dot(5)  # 在当前位置画一个直径为5的圆点（分钟刻度）
            skip(-radius)  # 移动回中心点
        turtle.right(6)  # 向右旋转6度（因为360度/60=6度）
'''
    以上函数中使用for-in语句控制循环执行60次,绘制60个刻度,通过if-else语句区分了画短线与原点两种情况
若能整除5则画短线,否则就画圆点.
'''

'''
(3) make_hand()函数
注册Turtle形状.钟表中的3个指针长度不同,但形状相似,为了防止冗余,使用make_hand()函数实现直线的绘制功能,
'''
def make_hand(name,length):
    '''注册turtle形状,建立名字为name的形状'''
    turtle.reset()  # 重置turtle状态
    skip(-0.1*length) # 向相反方向移动0.1倍长度（这样指针的起点不在中心，而是向后延伸一点，使得指针有尾部）
    turtle.begin_poly() # 开始记录多边形的顶点
    turtle.forward(1.1*length) # 向前移动1.1倍长度（指针的实际长度，多出0.1倍是为了让指针稍微超出中心，形成平衡）
    turtle.end_poly()   # turtle.begin_poly()/end_poly(): 记录多边形形状
    handform = turtle.get_poly() # 获取多边形顶点
    turtle.register_shape(name,handform)  # 将该多边形注册为名为name的形状
'''这个函数用于创建指针的形状，通过记录一条线段（带偏移）形成的多边形，然后注册为turtle的形状。'''
'''
(4) init()函数
功能是初始化程序,包括创建和初始化代表指针,日期,和周日期的Turtle对象.
'''
def init():
    global secHand,minHand,hurHand,printer
    # 重置turtle指针向北
    turtle.mode('logo')  # 设置turtle模式为“logo”，即0度指向正上方（北），
    # 且顺时针旋转（但注意：logo模式下默认是逆时针为正？实际上在logo模式下，0°是朝上，90°是朝右，而setheading(0)就是朝上）
    # 建立三个表针Turtle并初始化
    secHand = turtle.Turtle()  # 创建一个新的turtle对象，用于秒针
    make_hand('secHand',125)  # 创建名为'secHand'的形状，长度125
    secHand.shape('secHand')  # 将secHand对象的形状设置为刚刚注册的'secHand'
    minHand = turtle.Turtle()
    make_hand('minHand', 130)
    minHand.shape('minHand')
    hurHand = turtle.Turtle()
    make_hand('hurHand', 90)
    hurHand.shape('hurHand')
    for hand in secHand,minHand,hurHand:
        hand.shapesize(1,1,3) # hand.shapesize(1,1,3): 设置指针宽度1倍、长度1倍、轮廓线宽3像素
        hand.speed(0)
    # 建立并输出文字的turtle对象
    printer = turtle.Turtle()
    printer.hideturtle() # 隐藏画笔本身
    printer.penup()
    # 每个指针作为独立的Turtle对象，便于单独控制旋转和位置

'''
(5) week()和day()函数
'''
def week(t): # 参数：t - datetime对象
    week = ['星期一','星期二','星期三','星期四','星期五','星期六','星期天']
    return week[t.weekday()]
def day(t):
    return '%s %d %d' %(t.year,t.month,t.day)

'''
(6) tick()函数
功能是实时获取本地当前的日期时间,实时地显示日期,时间和周日期
'''
def tick():
    '''绘制钟表的动态展示'''
    t = datetime.today() # 获取当前时间
    second = t.second+t.microsecond*0.000001 # 秒数（加上微秒部分，转换成秒的小数）
    minute = t.minute + t.second/60 # 分钟数（加上秒转换成的分钟小数）
    hour = t.hour+t.minute/60 # 小时数（加上分钟转换成的小时小数）
    # 设置指针角度：秒针每秒钟6度（360/60=6），分针每分钟6度，时针每小时30度（360/12=30）
    secHand.setheading(second*6) # setheading()设置指针指向的角度
    minHand.setheading(minute*6)
    hurHand.setheading(hour*30)
    turtle.tracer(False) # 关闭自动刷新，避免部分绘制时的闪烁
    printer.fd(70) # printer.fd(70): 向上移动70像素写星期
    # 根据对齐(左,中或右)和给定字体,在当前龟位置写入文本
    printer.write(week(t),align='center',font=('courier',14,'bold')) # 写星期文本，居中，字体为Courier
    printer.back(130) # printer.back(130): 向下移动130像素（70+60）写日期
    printer.write(day(t),align='center',font=('courier',14,'bold'))
    # 将位置和方向恢复到出事状态,位置初始坐标为(0,0)
    # 方向初始为:standard 模式为right向右即东
    # logo模式为up向上即北
    printer.home()  # 回到中心点
    turtle.tracer(True)  # 开启自动刷新
    turtle.ontimer(tick,100) # 设置定时器，100毫秒后再次调用tick函数（即每秒调用10次，实现动画效果）
'''在 turtle 模块中，fd() 和 forward() 是完全相同的函数，back() 和 backward() 也是完全相同的函数。
    它们只是同一功能的不同命名方式，这是 turtle 模块设计的特性之一。'''
def main():
    # 关闭绘画追踪,可以用于加速绘画复杂图形
    turtle.tracer(False)
    init()
    # 画表框
    setup_clock(200)
    # 开启动画
    turtle.tracer(True)
    tick()
    # 启动事件循环,开始接收鼠标和键盘的操作
    turtle.done()

main()